package com.px.auth.security;

import com.px.auth.model.AuthReq;
import com.px.common.util.JsonUtil;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.Reader;

public class JsonAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
    private boolean postOnly = true;

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response){
        String contentType = request.getHeader("Content-Type");
        if (this.postOnly && !request.getMethod().equals("POST") || contentType == null) {
            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
        }

        AuthReq authReq;
        if (contentType.toLowerCase().contains("application/json")){
            authReq = getAuthFromJson(request);
        }else {
            authReq = getAuthFromFormData(request);
        }

        UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
                authReq.getUsername(), authReq.getPassword());
        setDetails(request, authRequest);
        return this.getAuthenticationManager().authenticate(authRequest);
    }

    protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) {
        authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
    }

    public void setPostOnly(boolean postOnly) {
        this.postOnly = postOnly;
    }

    private AuthReq getAuthFromJson(HttpServletRequest request) {
        AuthReq authReq;
        try (Reader reader = request.getReader()) {
            authReq = JsonUtil.getObjectMapper().readValue(reader, AuthReq.class);
        } catch (IOException e) {
            throw new AuthenticationServiceException("failed to get userid or password from request");
        }
        return authReq;
    }

    private AuthReq getAuthFromFormData(HttpServletRequest request) {
        String username = this.obtainUsername(request);
        String password = this.obtainPassword(request);

        if (StringUtils.isEmpty(username)
                || StringUtils.isEmpty(username.trim())
                || StringUtils.isEmpty(password)){
            throw new AuthenticationServiceException("failed to get userid or password from request");
        }
        return new AuthReq(username.trim(), password);
    }
}
